package com.lvcoding.spring5aop.spring;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author wuyanshen
 * @discription 模拟spring底层动态代理实现
 *  Spring底层使用BeanPostProcessor来生成代理对象
 *
 *  1. JDK动态代理(Spring默认使用的代理模式)
 *  2. CGLIB动态代理
 *
 *  注意：
 *  这里实现的代理，默认全部方法都会被代理，没有实现方法的切入点
 *
 * @date 2021-03-09 上午11:19
 */
// @Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    /**
     * 我们一般不做bean的初始化操作，所以这里直接返回bean，不做增强处理
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    /**
     * 我们在这做bean的增强操作，也就是为类生成代理对象
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        // 使用JDK动态代理(Spring默认使用的代理模式)
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("aop(jdk)：我在方法前执行了 =====");
                Object o = method.invoke(bean, args);
                System.out.println("aop(jdk)：我在方法后执行了 =====");
                return o;
            }
        };

        return Proxy.newProxyInstance(MyBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), invocationHandler);


        // CGLIB动态代理
        // MethodInterceptor methodInterceptor = new MethodInterceptor() {
        //     @Override
        //     public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        //         System.out.println("aop(cglib)：我在方法前执行了 =====");
        //         Object invoke = method.invoke(bean, objects);
        //         System.out.println("aop(cglib)：我在方法后执行了 =====");
        //         return invoke;
        //     }
        // };
        //
        // Enhancer enhancer = new Enhancer();
        // enhancer.setSuperclass(bean.getClass());
        // enhancer.setCallback(methodInterceptor);
        // return enhancer.create();
    }
}
